package com.keydom.ropeskipping.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.keydom.ropeskipping.AppApplication;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

public class CrashHandler  implements Thread.UncaughtExceptionHandler {
    private static CrashHandler mInstance;
    private Thread.UncaughtExceptionHandler mDefautHandler;
    private static final String TAG = "CrashHandlerTag";

    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        if (mInstance == null) {
            synchronized (CrashHandler.class) {
                if (mInstance == null) {
                    mInstance = new CrashHandler();
                }
            }
        }
        return mInstance;
    }

    public void init() {
        mDefautHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (ex != null) {
            // 收集设备信息、版本信息、异常信息
            String info = collectDeviceInfo(AppApplication.getInstance().getApplicationContext(), ex);
            // 本地存储
            saveInfo(info);
            Log.d(TAG, "已捕获到异常 ");

            //不进行延时处理的话kill不能执行完成
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    // 异常已经处理，结束进程
                    System.exit(1);

                }
            }, 100);

        } else {
            Log.d(TAG, "没有捕获异常 ");
            //没有处理还交给系统默认的处理器
            if (mDefautHandler != null) {
                mDefautHandler.uncaughtException(thread, ex);
            }
        }

    }

    /**
     * 收集设备信息
     *
     * @param c
     * @param ex
     */
    private String collectDeviceInfo(Context c, Throwable ex) {
        Map<String, String> infos = new HashMap<String, String>();
        //收集版本信息
        try {
            PackageManager pm = c.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(c.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionCode = pi.versionCode + "";
                String versionName = TextUtils.isEmpty(pi.versionName) ? "没有版本名称" : pi.versionName;
                infos.put("versionCode", versionCode);
                infos.put("versionName", versionName);
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        //收集设备信息
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {

            }
        }

        //收集异常信息
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();

        // 转化为字符串
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }
        sb.append(result);

        return sb.toString();
    }

    /**
     * 保存异常信息到本地
     * @param infos
     */
    private void saveInfo(String infos) {
        Log.d(TAG, "输出log日志: " + infos);
        // 把采集到的信息写入到本地文件
        LogLocalUtils.writeLogToFile(infos);
    }
}
